package cn.ctodb.wxmp.service;

import cn.ctodb.wxmp.config.MpConstants;
import cn.ctodb.wxmp.domain.Mp;
import cn.ctodb.wxmp.domain.Token;
import cn.ctodb.wxmp.domain.enumeration.TokenType;
import cn.ctodb.wxmp.repository.MpRepository;
import cn.ctodb.wxmp.repository.TokenRepository;
import cn.ctodb.wxmp.repository.search.TokenSearchRepository;
import cn.ctodb.wxmp.service.dto.TokenDTO;
import cn.ctodb.wxmp.service.mapper.TokenMapper;
import cn.ctodb.wxmp.util.HttpUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.inject.Inject;

import static org.elasticsearch.index.query.QueryBuilders.queryStringQuery;

/**
 * Service Implementation for managing Token.
 */
@Service
@Transactional
public class TokenService {

    private final Logger log = LoggerFactory.getLogger(TokenService.class);

    @Inject
    private TokenRepository tokenRepository;

    @Inject
    private TokenMapper tokenMapper;

    @Inject
    private TokenSearchRepository tokenSearchRepository;

    @Inject
    private MpRepository mpRepository;

    /**
     * Save a token.
     *
     * @param tokenDTO the entity to save
     * @return the persisted entity
     */
    public TokenDTO save(TokenDTO tokenDTO) {
        log.debug("Request to save Token : {}", tokenDTO);
        Token token = tokenMapper.tokenDTOToToken(tokenDTO);
        token = tokenRepository.save(token);
        TokenDTO result = tokenMapper.tokenToTokenDTO(token);
        tokenSearchRepository.save(token);
        return result;
    }

    /**
     * Get all the tokens.
     *
     * @param pageable the pagination information
     * @return the list of entities
     */
    @Transactional(readOnly = true)
    public Page<TokenDTO> findAll(Pageable pageable) {
        log.debug("Request to get all Tokens");
        Page<Token> result = tokenRepository.findAll(pageable);
        return result.map(token -> tokenMapper.tokenToTokenDTO(token));
    }

    /**
     * Get one token by id.
     *
     * @param id the id of the entity
     * @return the entity
     */
    @Transactional(readOnly = true)
    public TokenDTO findOne(Long id) {
        log.debug("Request to get Token : {}", id);
        Token token = tokenRepository.findOne(id);
        TokenDTO tokenDTO = tokenMapper.tokenToTokenDTO(token);
        return tokenDTO;
    }

    /**
     * Delete the  token by id.
     *
     * @param id the id of the entity
     */
    public void delete(Long id) {
        log.debug("Request to delete Token : {}", id);
        tokenRepository.delete(id);
        tokenSearchRepository.delete(id);
    }

    /**
     * Search for the token corresponding to the query.
     *
     * @param query the query of the search
     * @return the list of entities
     */
    @Transactional(readOnly = true)
    public Page<TokenDTO> search(String query, Pageable pageable) {
        log.debug("Request to search for a page of Tokens for query {}", query);
        Page<Token> result = tokenSearchRepository.search(queryStringQuery(query), pageable);
        return result.map(token -> tokenMapper.tokenToTokenDTO(token));
    }

    public Token getAccessToken(Long mpid) {
        Mp mp = mpRepository.getOne(mpid);
        Token token = tokenRepository.findOneByMpAndTokenType(mp, TokenType.GLOBAL);
        if (token == null) {
            token = new Token();
            token.setMp(mp);
            token.setTokenType(TokenType.GLOBAL);
            tokenRepository.save(token);
            return _getAccessToken(mp.getAppid(), mp.getAppsecret(), token);
        }
        if ((System.currentTimeMillis() - token.getTime()) / 1000 > token.getExpiresIn())
            return _getAccessToken(mp.getAppid(), mp.getAppsecret(), token);
        return token;
    }

    private Token _getAccessToken(String appid, String secret, Token token) {
        String requestUrl = MpConstants.ACCESS_TOKEN_URL.replace("APPID", appid).replace("SECRET", secret);
        String re = HttpUtils.get(requestUrl);
        if (null != re) {
            try {
                JSONObject jsonObject = new JSONObject(re);
                token.setAccessToken(jsonObject.getString("access_token"));
                token.setExpiresIn(jsonObject.getLong("expires_in"));
                token.setTime(System.currentTimeMillis());
                log.debug("获取token成功:" + token);
                return token;
            } catch (Exception e) {
                try {
                    JSONObject jsonObject = new JSONObject(re);
                    String error = String.format("获取token失败 errcode:{%s} errmsg:{%s}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
                    log.error(error, e);
                } catch (Exception e1) {
                }
            }
        }
        return null;
    }
}
